
#include <USSeg.h>
#include <FL/fl_file_chooser.H>

#include <time.h>
//#include <stdio.h>
#include <iostream>
#include "pdflib.hpp"



/************************************
 *
 *  Constructor
 *
 ***********************************/
USSeg
::USSeg()
{
	m_Proportion = 0;
	m_CannyOutputLevelSetViewer = InternalImageViewerType::New();
	m_GACOutputLevelSetViewer = InternalImageViewerType::New();
	m_OutputCannyEdgesViewer = RGBImageViewerType::New();
	m_InputImageViewer = InternalImageViewerType::New();
	
	m_ZeroSetImageViewer = InternalImageViewerType::New();
	m_FastMarchingImageViewer = RGBImageViewerType::New();
	m_GradientMagnitudeImageViewer = InternalImageViewerType::New();
	m_EdgePotentialImageViewer = InternalImageViewerType::New();
	m_InputImageViewerRGB = RGBImageViewerType::New();

	m_CannyThresholdedImageViewer = RGBImageViewerType::New();
	m_GACThresholdedImageViewer = RGBImageViewerType::New();

	m_RGBWriter = WriterType::New();
	RescaleFilter = RescaleFilterType::New();
	importFilter = ImportFilterType::New();
	RescaleFilter->SetOutputMinimum(   0 );
    RescaleFilter->SetOutputMaximum( 255 );

  m_InputImageViewer->SetClickCallBack( (void *)this,ClickSelectCallback);
  m_InputImageViewer->SetInteractionMode( fltk::Image2DViewerWindow::ClickMode );
  m_InputImageViewer->SetLabel("Select Seeds");

  m_CannyThresholdedImageViewer->SetLabel("Canny Segmentation Overlay Image");
  m_GACThresholdedImageViewer->SetLabel("GAC Segmentation Overlay Image");

  m_ZeroSetImageViewer->SetLabel("Fast Marching Output");

  m_FastMarchingImageViewer->SetLabel("Zero Set Image");

  m_GradientMagnitudeImageViewer->SetLabel("Gradient Magnitude Image");

  m_EdgePotentialImageViewer->SetLabel("Edge Potential Image");


  // Initialize ITK filter with GUI values
  m_CannySeg->m_SigmoidFilter->SetAlpha( sigmoidAlphaValueInput->value() );
  m_CannySeg->m_SigmoidFilter->SetBeta(  sigmoidBetaValueInput->value()  );

  m_CannySeg->SetZeroSetValue( zeroSetValueInput->value() );
  m_CannySeg->m_CannyFilter->SetNumberOfIterations( 
        static_cast<unsigned int>( USSegIterationsValueInput->value() ) );

  m_CannySeg->m_CannyFilter->SetMaximumRMSError( 
               USSegRMSErrorValueInput->value() );

  m_CannySeg->m_CannyFilter->SetCurvatureScaling(
               USSegCurvatureScalingValueInput->value() );

  m_CannySeg->m_CannyFilter->SetPropagationScaling(
               USSegPropagationScalingValueInput->value() );

 m_CannySeg->m_CannyFilter->SetAdvectionScaling(
               USSegAdvectionScalingValueInput->value() );

  m_CannySeg->m_CannyFilter->SetThreshold(
               USSegStrenghtThresholdValueInput->value() );

  m_CannySeg->m_CannyFilter->SetVariance( 
               USSegVarianceValueInput->value());

  m_CannySeg->m_DerivativeFilter->SetSigma( sigmaValueInput->value() );

  m_CannySeg->m_FastMarchingFilter->SetStoppingValue( fastMarchingStoppingValueInput->value() );

  m_CannyOutputLevelSetViewer->SetLabel("Canny Output Level Set");
  m_GACOutputLevelSetViewer->SetLabel("GAC Output Level Set");
  m_OutputCannyEdgesViewer->SetLabel("Segmentation Edges");


  m_GACSeg->m_SigmoidFilter->SetAlpha( sigmoidAlphaValueInput->value() );
  m_GACSeg->m_SigmoidFilter->SetBeta(  sigmoidBetaValueInput->value()  );

  m_GACSeg->SetZeroSetValue( zeroSetValueInput->value() );
  m_GACSeg->m_GeodesicActiveContourFilter->SetNumberOfIterations( 
        static_cast<unsigned int>( USSegIterationsValueInput->value() ) );

  m_GACSeg->m_GeodesicActiveContourFilter->SetMaximumRMSError( 
               USSegRMSErrorValueInput->value() );

  m_GACSeg->m_GeodesicActiveContourFilter->SetCurvatureScaling(
               USSegCurvatureScalingValueInput->value() );

  m_GACSeg->m_GeodesicActiveContourFilter->SetPropagationScaling(
               USSegPropagationScalingValueInput->value() );

 m_GACSeg->m_GeodesicActiveContourFilter->SetAdvectionScaling(
               USSegAdvectionScalingValueInput->value() );


  m_GACSeg->m_DerivativeFilter->SetSigma( sigmaValueInput->value() );

  m_GACSeg->m_FastMarchingFilter->SetStoppingValue( fastMarchingStoppingValueInput->value() );

  // Connect Observers in the GUI 
//  inputImageButton->Observe( m_ImageReader.GetPointer() );
 // thresholdedImageButton->Observe( m_ThresholdFilter.GetPointer() );
 // outputLevelSetButton->Observe( m_CannyFilter.GetPointer() );
 // gradientMagnitudeButton->Observe( m_DerivativeFilter.GetPointer() );
 // edgePotentialButton->Observe( m_SigmoidFilter.GetPointer() );
 // fastMarchingResultButton->Observe( m_FastMarchingFilter.GetPointer() );
//  outputCannyEdgesButton->Observe( m_CannyFilter.GetPointer() );
//  contourExportVTKButton->Observe( m_CannyFilter.GetPointer() );

  progressSlider->Observe( m_CannySeg->m_CastImageFilter2DsTo3Df.GetPointer() );
  progressSlider->Observe( m_CannySeg->m_DerivativeFilter.GetPointer() );
  progressSlider->Observe( m_CannySeg->m_ThresholdFilter.GetPointer() );
  progressSlider->Observe( m_CannySeg->m_SigmoidFilter.GetPointer() );
  progressSlider->Observe( m_CannySeg->m_ImageReader.GetPointer() );
  progressSlider->Observe( m_CannySeg->m_CannyFilter.GetPointer() );
  progressSlider->Observe( m_CannySeg->m_FastMarchingFilter.GetPointer() );
  progressSlider->Observe( m_CannySeg->m_InputThresholdFilter.GetPointer() );
  progressSlider->Observe( m_GACSeg->m_CastImageFilter2DsTo3Df.GetPointer() );
  progressSlider->Observe( m_GACSeg->m_DerivativeFilter.GetPointer() );
  progressSlider->Observe( m_GACSeg->m_ThresholdFilter.GetPointer() );
  progressSlider->Observe( m_GACSeg->m_SigmoidFilter.GetPointer() );
  progressSlider->Observe( m_GACSeg->m_ImageReader.GetPointer() );
  progressSlider->Observe( m_GACSeg->m_GeodesicActiveContourFilter.GetPointer() );
  progressSlider->Observe( m_GACSeg->m_FastMarchingFilter.GetPointer() );
  progressSlider->Observe( m_GACSeg->m_InputThresholdFilter.GetPointer() );
  

}



/************************************
 *
 *  Destructor
 *
 ***********************************/
USSeg
::~USSeg()
{

}




/************************************
 *
 * Show main console
 *
 ***********************************/
void
USSeg
::ShowConsole(void)
{
  consoleWindow->show();
  CannyGroup->deactivate();
  GACGroup->deactivate();
  Clearseeds->deactivate();
}




/********************************************
 *
 * Quit : requires to hide all fltk windows
 *
 *******************************************/
void
USSeg
::Quit(void)
{
  m_InputImageViewer->Hide();
  m_CannyThresholdedImageViewer->Hide();
  m_GACThresholdedImageViewer->Hide();
  m_EdgePotentialImageViewer->Hide();
  m_GradientMagnitudeImageViewer->Hide();
  m_CannyOutputLevelSetViewer->Hide();
    m_GACOutputLevelSetViewer->Hide();
  m_ZeroSetImageViewer->Hide();
  m_FastMarchingImageViewer->Hide();
  m_OutputCannyEdgesViewer->Hide();
  m_InputImageViewerRGB->Hide();
  
  consoleWindow->hide();
}






 
/************************************
 *
 *  Load Input Image
 *
 ***********************************/
void
USSeg
::LoadInputImage( void )
{

  const char * filename = fl_file_chooser("Input Image filename","*.*","");
  if( !filename )
  {
    return;
  }

  this->ShowStatus("Loading input image file...");
  
  try 
  {
    USSegBase::LoadInputImage( filename );
  }
  catch( itk::ExceptionObject & excp ) 
  {
    fl_alert( excp.GetDescription() );
    CannyGroup->deactivate();
	GACGroup->deactivate();
	Clearseeds->deactivate();
    return;
  }
  catch( ... ) 
  {
    this->ShowStatus("Problems reading file format");
    CannyGroup->deactivate();
	GACGroup->deactivate();
	Clearseeds->deactivate();
    return;
  }

  this->ShowStatus("Input Image Loaded");

  CannyGroup->activate();
  GACGroup->activate();
  Clearseeds->activate();
  this->ShowInputImage();

}


 
/****************************************************************
 *
 *  Export contour representing the Iso-value of the LevelSet
 *
 ***************************************************************/
/*
void
USSeg
::ExportContour( void )
{
  const char * filename = fl_file_chooser("Contour filename","*.vtk","");
  if( !filename )
    {
    return;
    }
  m_GACSeg->m_PolyDataWriter->SetFileName( filename );
  m_GACSeg->m_PolyDataWriter->Write();
}
*/

 
/************************************
 *
 *  Show Status
 *
 ***********************************/
void
USSeg
::ShowStatus( const char * message )
{
  statusTextOutput->value( message );
  Fl::check();
}




 
/************************************
 *
 *  Show Input Image
 *
 ***********************************/
void
USSeg
::ShowInputImage( void )
{

  if( !m_GACSeg->m_InputImageIsLoaded||!m_CannySeg->m_InputImageIsLoaded )
    {
    return;
    }

  m_GACSeg->m_CastImageFilter2DsTo2Df->UpdateLargestPossibleRegion();
  m_CannySeg->m_CastImageFilter2DsTo2Df->UpdateLargestPossibleRegion();
  m_InputImageViewer->SetImage( m_GACSeg->m_CastImageFilter2DsTo2Df->GetOutput() );
//  inputViewer->SetImage( m_CastImageFilter2DsTo2Df->GetOutput() );
//  inputViewer->Show();
  int sizeX = m_GACSeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[0] ;
  int sizeY = m_GACSeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] ;

m_InputImageViewerRGB->SetLabel("Seeds View");
  m_InputImageViewerRGB->SetRedChannel( m_GACSeg->m_SeedImage );
  m_InputImageViewerRGB->SetGreenChannel( m_GACSeg->m_CastImageFilter2DsTo2Df->GetOutput() ); 
  m_InputImageViewerRGB->FillChannel(2, 0, sizeX, sizeY) ;

//  m_InputImageViewerRGB->SetImage( m_CastImageFilter2DsTo2Df->GetOutput() );
 //  m_InputImageViewerRGB->SetOverlay( m_SeedImage );
 // m_InputImageViewerRGB->intensityWindow->position(300,300);
	
  m_InputImageViewerRGB->imageViewer->FitWindowToImage();
  m_InputImageViewerRGB->Show();
	m_InputImageViewer->imageViewer->FitWindowToImage();   
  m_InputImageViewer->Show();


}




 
/************************************
 *
 *  Show LevelSet Output
 *
 ***********************************/
void
USSeg
::ShowCannyOutputLevelSet( void )
{

  if( !m_CannySeg->m_InputImageIsLoaded )
    {
    return;
    }
  this->RunCanny();

  m_CannyOutputLevelSetViewer->SetImage( m_CannySeg->m_CannyFilter->GetOutput() ); 
  m_CannyOutputLevelSetViewer->imageViewer->FitWindowToImage();
  m_CannyOutputLevelSetViewer->Update();
  m_CannyOutputLevelSetViewer->Show();

}
void
USSeg
::ShowGACOutputLevelSet( void )
{

  if( !m_GACSeg->m_InputImageIsLoaded )
    {
    return;
    }
  this->RunGeodesicActiveContour();

  m_GACOutputLevelSetViewer->SetImage( m_GACSeg->m_GeodesicActiveContourFilter->GetOutput() ); 
  m_GACOutputLevelSetViewer->imageViewer->FitWindowToImage();
  m_GACOutputLevelSetViewer->Update();
  m_GACOutputLevelSetViewer->Show();

}

  

 
/*******************************************************
 *
 *  Show CannyEdges Output overlaid to input image 
 *
 ******************************************************/
/*
void
USSeg
::ShowOutputCannyEdges( void )
{

  if( !m_GACSeg->m_InputImageIsLoaded )
    {
    return;
    }
  this->RunCanny();


  int sizeX = m_GACSeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[0] ;
  int sizeY = m_GACSeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] ;

  m_OutputCannyEdgesViewer->SetRedChannel( m_GACSeg->m_CannyEdgesThresholdFilter->GetOutput() );
  m_OutputCannyEdgesViewer->SetGreenChannel( m_GACSeg->m_CastImageFilter2DsTo2Df->GetOutput() ); 
  m_OutputCannyEdgesViewer->FillChannel(2, 0, sizeX, sizeY) ;
  m_OutputCannyEdgesViewer->imageViewer->FitWindowToImage();
  m_OutputCannyEdgesViewer->Show();

}
*/



/************************************
 *
 *  Show Gradient Magnitude
 *
 ***********************************/

/*void
USSeg
::ShowGradientMagnitudeImage( void )
{

  if( !m_GACSeg->m_InputImageIsLoaded )
    {
    return;
    }
  this->ComputeGradientMagnitude();


  m_GradientMagnitudeImageViewer->SetImage( m_GACSeg->m_DerivativeFilter->GetOutput() );  
    m_GradientMagnitudeImageViewer->imageViewer->FitWindowToImage();
  m_GradientMagnitudeImageViewer->Show();

}
*/


 
/************************************
 *
 *  Show The Edge Potential Map
 *
 ***********************************/
void
USSeg
::ShowEdgePotentialImage( void )
{

  if( !m_Segmentation->m_InputImageIsLoaded )
    {
    return;
    }

this->ComputeEdgePotential();
  m_EdgePotentialImageViewer->SetImage( m_Segmentation->m_SigmoidFilter->GetOutput() );  
      m_EdgePotentialImageViewer->imageViewer->FitWindowToImage();
  m_EdgePotentialImageViewer->Show();

}





 
/************************************
 *
 *  Show Thresholded Image
 *
 ***********************************/
void
USSeg
::ShowGACThresholdedImage( void )
{
this->ShowStatus("Please wait...");
  int sizeX = m_GACSeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[0] ;
  int sizeY = m_GACSeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] ;
//  m_CastImageFilter2DsTo2Df->UpdateLargestPossibleRegion();
  m_GACSeg->m_ThresholdFilter->UpdateLargestPossibleRegion();
 /*
  m_CastImageFilter2DcTo3Dc = CastImage2DcTo3DcFilterType::New();
  m_CastImageFilter2DcTo3Dc->SetInput( m_ThresholdFilter->GetOutput() );
  m_CastImageFilter2DcTo3Dc->UpdateLargestPossibleRegion();
*/

  m_GACThresholdedImageViewer->SetRedChannel( m_GACSeg->m_ThresholdFilter->GetOutput() );
  m_GACThresholdedImageViewer->SetGreenChannel( m_GACSeg->m_CastImageFilter2DsTo2Df->GetOutput() ); 
  m_GACThresholdedImageViewer->FillChannel(2, 0, sizeX, sizeY) ;
      m_GACThresholdedImageViewer->imageViewer->FitWindowToImage();
this->ShowStatus("Done.");
m_GACThresholdedImageViewer->Update();
  m_GACThresholdedImageViewer->Show();
  CalculateSegmentationProportion();
//  m_CannyThresholdedImageViewer->SetOverlayOpacity( 0.5 );

}
void
USSeg
::ShowCannyThresholdedImage( void )
{
this->ShowStatus("Please wait...");
  int sizeX = m_CannySeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[0] ;
  int sizeY = m_CannySeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] ;
//  m_CastImageFilter2DsTo2Df->UpdateLargestPossibleRegion();
  m_CannySeg->m_ThresholdFilter->UpdateLargestPossibleRegion();
 /*
  m_CastImageFilter2DcTo3Dc = CastImage2DcTo3DcFilterType::New();
  m_CastImageFilter2DcTo3Dc->SetInput( m_ThresholdFilter->GetOutput() );
  m_CastImageFilter2DcTo3Dc->UpdateLargestPossibleRegion();
*/

  m_CannyThresholdedImageViewer->SetRedChannel( m_CannySeg->m_ThresholdFilter->GetOutput() );
  m_CannyThresholdedImageViewer->SetGreenChannel( m_CannySeg->m_CastImageFilter2DsTo2Df->GetOutput() ); 
  m_CannyThresholdedImageViewer->FillChannel(2, 0, sizeX, sizeY) ;
      m_CannyThresholdedImageViewer->imageViewer->FitWindowToImage();
this->ShowStatus("Done.");
m_CannyThresholdedImageViewer->Update();
  m_CannyThresholdedImageViewer->Show();
  CalculateSegmentationProportion();
//  m_CannyThresholdedImageViewer->SetOverlayOpacity( 0.5 );

}




 
/************************************
 *
 *  Show Fast Marching Result Image
 *
 ***********************************/
/*void
USSeg
::ShowFastMarchingResultImage( void )
{
  m_GACSeg->m_CastImageFilter2DsTo2Df->UpdateLargestPossibleRegion();
 m_GACSeg->m_InputThresholdFilter->UpdateLargestPossibleRegion();

  int sizeX = m_GACSeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[0] ;
  int sizeY = m_GACSeg->m_ImageReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] ;
	m_FastMarchingImageViewer->imageViewer->FitWindowToImage();

  m_FastMarchingImageViewer->SetRedChannel( m_GACSeg->m_InputThresholdFilter->GetOutput() );
  m_FastMarchingImageViewer->SetGreenChannel( m_GACSeg->m_CastImageFilter2DsTo2Df->GetOutput() ); 
  m_FastMarchingImageViewer->FillChannel(2, 0, sizeX, sizeY) ;
      
  m_FastMarchingImageViewer->Show();
}



*/

 
/*****************************************
 *
 *  Callback for Selecting a seed point
 *
 *****************************************/
void
USSeg
::ClickSelectCallback( void * args, int& x, int& y )
{

  USSeg * self = 
     static_cast<USSeg *>( args );

  self->SelectSeedPoint( x, y );

}



 
/*****************************************
 *
 *  Callback for Selecting a seed point
 *
 *****************************************/
void
USSeg
::SelectSeedPoint(int x, int y)
{

  typedef SeedImageType::IndexType IndexType;
  IndexType seed;
  seed[0] = static_cast<IndexType::IndexValueType>( x );
  seed[1] = static_cast<IndexType::IndexValueType>( y );
//  seed[2] = static_cast<IndexType::IndexValueType>( z );

  USSegBase::AddSeed( seed );
//	m_CastImageFilter2DcTo3DcSeed->UpdateLargestPossibleRegion();
    m_InputImageViewerRGB->SetRedChannel( m_Segmentation->m_SeedImage );
//  m_InputImageViewerRGB->SetGreenChannel( m_CastImageFilter2DsTo2Df->GetOutput() ); 
//  m_InputImageViewerRGB->FillChannel(2, 0, sizeX, sizeY) ;

  m_InputImageViewerRGB->imageViewer->FitWindowToImage();
  m_InputImageViewerRGB->Update();

}


  
  

  
/*****************************************
 *
 *  Clear the seed used to generate the 
 *  initial level set front
 *
 *****************************************/
void
USSeg
::ClearSeeds()
{
  this->USSegBase::ClearSeeds();
  m_ZeroSetImageViewer->Update();
  m_InputImageViewerRGB->SetRedChannel( m_Segmentation->m_SeedImage );
  m_InputImageViewerRGB->imageViewer->FitWindowToImage();
  m_InputImageViewerRGB->Update();
  m_InputImageViewer->imageViewer->FitWindowToImage();
  m_InputImageViewer->Update();
  Fl::check();
}
  
 
void
USSeg
::CalculateSegmentationProportion()
{
  itk::ImageRegionConstIteratorWithIndex<InternalImageType2Df> iterBinaryImage( m_Segmentation->m_ThresholdFilter->GetOutput(), m_Segmentation->m_ThresholdFilter->GetOutput()->GetLargestPossibleRegion() );
  itk::ImageRegionConstIteratorWithIndex<InternalImageType2Df>::IndexType currentIndex;
//  itk::ImageRegionConstIteratorWithIndex<InternalImageType2Df>::IndexType minIndex; 
//  for (unsigned int i = 0; i < ImageDimension2D; ++i) minIndex[i] = std::numeric_limits<long int>::max();

 // itk::ImageRegionConstIteratorWithIndex<InternalImageType2Df>::IndexType maxIndex; 

 // for (unsigned int i = 0; i < ImageDimension2D; ++i) maxIndex[i] = std::numeric_limits<long int>::min();
 
//  m_CenterOfMass.Fill(0.0);
  
  m_Proportion = 0;
  while (!iterBinaryImage.IsAtEnd())
  {
    if ( iterBinaryImage.Get() > static_cast<InternalPixelType>(0.0) )
    {
      // update center of mass
      currentIndex = iterBinaryImage.GetIndex();
      itk::Vector<float, ImageDimension2D> currentPoint;  
      for (unsigned int i = 0; i < ImageDimension2D; ++i) currentPoint[i] = currentIndex[i];
    
 //     m_CenterOfMass =    (m_CenterOfMass * ( static_cast<float>(m_Proportion) / static_cast<float>(m_Proportion+1) ) )  // e.g. 3 points:   old center * 2/3 + currentPoint * 1/3;
   //          + currentPoint / static_cast<float>(m_Proportion+1);
      
      // update number of voxels
      ++m_Proportion;

 /*     // update bounding box
      for (unsigned int i = 0; i < ImageDimension2D; ++i) 
      {
        if (currentIndex[i] < minIndex[i]) minIndex[i] = currentIndex[i];
        if (currentIndex[i] > maxIndex[i]) maxIndex[i] = currentIndex[i];
      }*/
    }
	
    ++iterBinaryImage;
  }

/*  m_MinIndexOfBoundingBox[2] = 0.0;
  m_MaxIndexOfBoundingBox[2] = 0.0;
  for (unsigned int i = 0; i < ImageDimension2D; ++i) 
  {
    m_MinIndexOfBoundingBox[i] = minIndex[i];
    m_MaxIndexOfBoundingBox[i] = maxIndex[i];
  }
  */
  
  cout<<m_Proportion<<"Pixels;";
	char s_proportion[255];
	sprintf(s_proportion, "Proportion: %dPixels.", m_Proportion);
	this->ShowStatus(s_proportion);

}
  
void
USSeg
::SaveResultImage( void)
{
	  
/*
//	 m_ImageSize = image->GetRequestedRegion().GetSize() ;
//    this->externalWindow->size(m_ImageSize[0], m_ImageSize[1]);
 //   imageViewer->Allocate( m_ImageSize[0], m_ImageSize[1] );

	itk::RGBPixel * localBuffer = new PixelType[ numberOfPixels ]; 

    // Fill the Image
 
    itk::ImageLinearConstIteratorWithIndex< ImageType > 
                                        it( image, image->GetRequestedRegion() );

    const int bytesPerPixel = imageViewer->GetNumberOfBytesPerPixel();

    it.SetDirection( 0 );

    const unsigned int totalSize  =
                m_ImageSize[0] * m_ImageSize[1] * bytesPerPixel;

    const unsigned int totalWidth = m_ImageSize[0] * bytesPerPixel;

    fltk::RGBImage2DViewerWindow::ValueType * buffer = imageViewer->GetBuffer();

    if(!m_FlipY)
      {
      unsigned char * dest = buffer + totalSize + 3 - totalWidth;
      it.GoToBegin();
      while( !it.IsAtEnd() )  // Should only have one slice...but anyway.
        {
        while( !it.IsAtEndOfLine() ) 
          { 
          const double valueR = it.Get().GetRed();
          const unsigned char valuecR = static_cast<unsigned char>( valueR );
          *dest = valuecR;
          dest++;
          const double valueG = it.Get().GetGreen();
          const unsigned char valuecG = static_cast<unsigned char>( valueG );
          *dest = valuecG;
          dest++;
          const double valueB = it.Get().GetBlue();
          const unsigned char valuecB = static_cast<unsigned char>( valueB );
          *dest = valuecB;
          dest++;
          ++it;
          }
        it.NextLine();
        dest -= 2 * totalWidth;
        }
      }
    else
      {
      unsigned char * dest = buffer;
      
      it.GoToBegin();
      while( !it.IsAtEnd() )  // Should only have one slice...but anyway.
        {
        while( !it.IsAtEndOfLine() ) 
          { 
          const double valueR = it.Get().GetRed();
          const unsigned char valuecR = static_cast<unsigned char>( valueR );
          *dest = valuecR;
          dest++;
          const double valueG = it.Get().GetGreen();
          const unsigned char valuecG = static_cast<unsigned char>( valueG );
          *dest = valuecG;
          dest++;
          const double valueB = it.Get().GetBlue();
          const unsigned char valuecB = static_cast<unsigned char>( valueB );
          *dest = valuecB;
          dest++;
          ++it;
          }
        it.NextLine();
        }
	}
	
	  ImportFilterType::SizeType  size;
size[0]  = m_CannyThresholdedImageViewer->imageViewer->GetWidth();  // size along X
  size[1]  = m_CannyThresholdedImageViewer->imageViewer->GetHeight();  // size along Y
	const unsigned int numberOfPixels = size[0] * size[1];

  ImportFilterType::IndexType start;
  start.Fill( 0 );

  ImportFilterType::RegionType region;
  region.SetIndex( start );
  region.SetSize(  size  );
   importFilter->SetRegion( region );

  double origin[ 2 ];
  origin[0] = 0.0;    // X coordinate 
  origin[1] = 0.0;    // Y coordinate
 // origin[2] = 0.0;    // Z coordinate

  importFilter->SetOrigin( origin );
  
  double spacing[ 2 ];
  spacing[0] = 1.0;    // along X direction 
  spacing[1] = 1.0;    // along Y direction
//  spacing[2] = 1.0;    // along Z direction

  importFilter->SetSpacing( spacing );
  const bool importImageFilterWillOwnTheBuffer = true;
  importFilter->SetImportPointer( m_CannyThresholdedImageViewer->imageViewer->GetBuffer(), numberOfPixels, 
                                  importImageFilterWillOwnTheBuffer );

	*/
	RescaleFilter->SetInput( m_Segmentation->m_ThresholdFilter->GetOutput() );
	  m_RGBWriter->SetInput(RescaleFilter->GetOutput());
//	    m_RGBWriter->SetInput(importFilter->GetOutput());
	char newname[255];
	char * filename = fl_file_chooser("Image Filename","*.{jpg(default),raw,mhd,mha,VOL,jpeg,tif,tiff,png,vtk}","");
	 if( !filename )
    {
    return;
    }
	 if(!strstr(filename,".jpg")&&!strstr(filename,".raw")&&!strstr(filename,".mhd")&&!strstr(filename,".mha")&&!strstr(filename,".vol")&&!strstr(filename,".tif")&&!strstr(filename,".tiff")&&!strstr(filename,".png")&&!strstr(filename,".vtk"))
	 {
		 strcpy(newname, filename);	
		 strcat(newname,".jpg");
	 }
  m_RGBWriter->SetFileName( newname );
  m_RGBWriter->Write();
  

}

void
USSeg
::SavePDF(void)
{
	  if( !m_Segmentation->m_InputImageIsLoaded )
    {
    return;
    }
	  
	  try {
	/*  This is where the data files are. Adjust as necessary. */
	RescaleFilter->SetInput( m_Segmentation->m_CastImageFilter2DsTo2Df->GetOutput()  );
	  m_RGBWriter->SetInput(RescaleFilter->GetOutput());
//	    m_RGBWriter->SetInput(importFilter->GetOutput());
  m_RGBWriter->SetFileName( "USSegInputTemp.jpg" );
  m_RGBWriter->Write();
  
  
		RescaleFilter->SetInput( m_CannySeg->m_ThresholdFilter->GetOutput() );
	  m_RGBWriter->SetInput(RescaleFilter->GetOutput());
//	    m_RGBWriter->SetInput(importFilter->GetOutput());
  m_RGBWriter->SetFileName( "USSegtemp1.jpg" );
  m_RGBWriter->Write();

  	RescaleFilter->SetInput( m_GACSeg->m_ThresholdFilter->GetOutput() );
	  m_RGBWriter->SetInput(RescaleFilter->GetOutput());
//	    m_RGBWriter->SetInput(importFilter->GetOutput());
	
  m_RGBWriter->SetFileName( "USSegtemp2.jpg" );
  m_RGBWriter->Write();

	itk::ImageRegionConstIteratorWithIndex<InternalImageType2Df> iterBinaryImage1( m_CannySeg->m_ThresholdFilter->GetOutput(), m_Segmentation->m_ThresholdFilter->GetOutput()->GetLargestPossibleRegion() );
  itk::ImageRegionConstIteratorWithIndex<InternalImageType2Df>::IndexType currentIndex1;
  m_Proportion = 0;
  while (!iterBinaryImage1.IsAtEnd())
  {
    if ( iterBinaryImage1.Get() > static_cast<InternalPixelType>(0.0) )
    {
      // update center of mass
      currentIndex1 = iterBinaryImage1.GetIndex();
      itk::Vector<float, ImageDimension2D> currentPoint;  
      for (unsigned int i = 0; i < ImageDimension2D; ++i) currentPoint[i] = currentIndex1[i];
      ++m_Proportion;
    }
    ++iterBinaryImage1;
  }
	char s_proportion1[255];
	sprintf(s_proportion1, "Proportion: %d Pixels.", m_Proportion);

	itk::ImageRegionConstIteratorWithIndex<InternalImageType2Df> iterBinaryImage2( m_GACSeg->m_ThresholdFilter->GetOutput(), m_Segmentation->m_ThresholdFilter->GetOutput()->GetLargestPossibleRegion() );
  m_Proportion = 0;
  while (!iterBinaryImage2.IsAtEnd())
  {
    if ( iterBinaryImage2.Get() > static_cast<InternalPixelType>(0.0) )
    {
      // update center of mass
      currentIndex1 = iterBinaryImage2.GetIndex();
      itk::Vector<float, ImageDimension2D> currentPoint;  
      for (unsigned int i = 0; i < ImageDimension2D; ++i) currentPoint[i] = currentIndex1[i];
      ++m_Proportion;
    }
    ++iterBinaryImage2;
  }
	char s_proportion2[255];
	sprintf(s_proportion2, "Proportion: %d Pixels.", m_Proportion);
	

	PDFlib p;
//	string imagefile = "nesrin.jpg";
	int font, image0, image1, image2;

	//  This means we must check return values of load_font() etc.
	p.set_parameter("errorpolicy", "return");

	p.set_parameter("SearchPath", "./");

	// This line is required to avoid problems on Japanese systems
	p.set_parameter("hypertextencoding", "host");

	char newname[255];
	char * filename = fl_file_chooser("PDF Filename","*.pdf","");
	 if( !filename )
    {
    return;
    }
	 if(!strstr(filename,".pdf"))
	 {
		 strcpy(newname, filename);	
		 strcat(newname,".pdf");
	 }

	if (p.begin_document(newname, "") == -1) {
	    cerr << "Error: " << p.get_errmsg() << endl; //return 2;
	}

	p.set_info("Creator", "USSeg");
	p.set_info("Title", "Segmentation Comparison");

	/*  We load the image before the first page, and use it
	    on all pages
	 */
	image0 = p.load_image("auto", "USSegInputTemp.jpg", "");
	image1 = p.load_image("auto", "USSegtemp1.jpg", "");
	image2 = p.load_image("auto", "USSegtemp2.jpg", "");

	if ((image1 == -1) || (image2 == -1)) {
	    cerr << "Error: " << p.get_errmsg() << endl; //return 2;
	}

	/*  Page 1 */
	p.begin_page_ext(595, 842, "");

	/*  For PDFlib Lite: change "unicode" to "winansi" */


//	p.set_text_pos(50, 700);
//	p.show("Hello world!");


	font = p.load_font("Helvetica", "winansi", "");
	if (font == -1) {
	    cerr << "Error: " << p.get_errmsg() << endl;// return(2);
	}


	 char dateStr [9], title[80];
     _strdate( dateStr);
	sprintf(title, " Created by USSeg on %s.", dateStr );
	p.setfont(font, 10);
	p.set_text_pos(360, 40);
	p.show(title);

	/*  Fit the image to a box of predefined size (without distortion) */
	std::string optlist("boxsize={235 240} position={center} fitmethod=meet");
//	std::string optlist1("boxsize={235 240} position={center} fitmethod=meet");
	std::string optlistStr("boxsize={235 10} position={center} fontsize=12");
	std::string optlistStr1("boxsize={235 10} position={center} fontsize=10");
	p.fit_image(image0, 180, 540, optlist);
	p.fit_image(image1, 46, 250, optlist);
	p.fit_image(image2, 309, 250, optlist);
	
	p.fit_textline("Original Image",180, 520,optlistStr);
	p.fit_textline("Canny Segmentation",46, 230,optlistStr);
	p.fit_textline("GeodesicActiveContour Segmentation",314, 230,optlistStr);
	p.fit_textline(s_proportion1,46, 212,optlistStr1);
	p.fit_textline(s_proportion2,314, 212,optlistStr1);

	p.end_page_ext("");

	p.close_image(image0);
	p.close_image(image1);
	p.close_image(image2);
	p.end_document("");

	DeleteFile("USSegtemp1.jpg");
	DeleteFile("USSegtemp2.jpg");
	DeleteFile("USSegInputTemp.jpg");
    }

    catch (PDFlib::Exception &ex) {
	cerr << "PDFlib exception occurred:" << endl;
	cerr << "[" << ex.get_errnum() << "] " << ex.get_apiname()
	    << ": " << ex.get_errmsg() << endl;
//	return 2;
    }

}

/*  Finaly the main() that will instantiate the application  */
int main()
{

  try 
    {
    USSeg * console = new USSeg();
    console->ShowConsole();
    Fl::run();
    delete console;
    }
  catch( itk::ExceptionObject & e )
    {
    std::cerr << "ITK exception caught in main" << std::endl;
    std::cerr << e << std::endl;
    }
  catch( std::exception & e )
    {
    std::cerr << "STD exception caught in main" << std::endl;
    std::cerr << e.what() << std::endl;
    }
  catch( ... )
    {
    std::cerr << "unknown exception caught in main" << std::endl;
    }


  return 0;

}



